// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.core.skinnedmodel.model;

import java.nio.FloatBuffer;
import java.util.ArrayList;
import org.joml.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
import org.lwjglx.BufferUtils;
import zombie.core.Core;
import zombie.core.math.PZMath;
import zombie.core.skinnedmodel.ModelManager;
import zombie.core.skinnedmodel.animation.AnimationPlayer;
import zombie.core.textures.Texture;
import zombie.debug.DebugLog;
import zombie.popman.ObjectPool;
import zombie.scripting.objects.ModelAttachment;
import zombie.util.Pool;
import zombie.util.StringUtils;
import zombie.util.Type;
import zombie.vehicles.BaseVehicle;

public final class ModelInstanceRenderData {
    private static final Vector3f tempVector3f = new Vector3f();
    public Model model;
    public Texture tex;
    public float depthBias;
    public float hue;
    public float tintR;
    public float tintG;
    public float tintB;
    public int parentBone;
    public FloatBuffer matrixPalette;
    public final Matrix4f xfrm = new Matrix4f();
    public SoftwareModelMeshInstance softwareMesh;
    public ModelInstance modelInstance;
    public boolean m_muzzleFlash = false;
    protected ModelInstanceDebugRenderData m_debugRenderData;
    private static final ObjectPool<ModelInstanceRenderData> pool = new ObjectPool<>(ModelInstanceRenderData::new);

    public ModelInstanceRenderData init(ModelInstance _modelInstance) {
        this.model = _modelInstance.model;
        this.tex = _modelInstance.tex;
        this.depthBias = _modelInstance.depthBias;
        this.hue = _modelInstance.hue;
        this.parentBone = _modelInstance.parentBone;

        assert _modelInstance.character == null || _modelInstance.AnimPlayer != null;

        this.m_muzzleFlash = false;
        this.xfrm.identity();
        if (_modelInstance.AnimPlayer != null && !this.model.bStatic) {
            SkinningData skinningData = (SkinningData)this.model.Tag;
            if (Core.bDebug && skinningData == null) {
                DebugLog.General.warn("skinningData is null, matrixPalette may be invalid");
            }

            org.lwjgl.util.vector.Matrix4f[] matrix4f = _modelInstance.AnimPlayer.getSkinTransforms(skinningData);
            if (this.matrixPalette == null || this.matrixPalette.capacity() < matrix4f.length * 16) {
                this.matrixPalette = BufferUtils.createFloatBuffer(matrix4f.length * 16);
            }

            this.matrixPalette.clear();

            for (int _int = 0; _int < matrix4f.length; _int++) {
                matrix4f[_int].store(this.matrixPalette);
            }

            this.matrixPalette.flip();
        }

        VehicleSubModelInstance vehicleSubModelInstance = Type.tryCastTo(_modelInstance, VehicleSubModelInstance.class);
        if (_modelInstance instanceof VehicleModelInstance || vehicleSubModelInstance != null) {
            if (_modelInstance instanceof VehicleModelInstance) {
                this.xfrm.set(((BaseVehicle)_modelInstance.object).renderTransform);
            } else {
                this.xfrm.set(vehicleSubModelInstance.modelInfo.renderTransform);
            }

            if (_modelInstance.model.Mesh != null && _modelInstance.model.Mesh.isReady() && _modelInstance.model.Mesh.m_transform != null) {
                _modelInstance.model.Mesh.m_transform.transpose();
                this.xfrm.mul(_modelInstance.model.Mesh.m_transform);
                _modelInstance.model.Mesh.m_transform.transpose();
            }
        }

        this.softwareMesh = _modelInstance.softwareMesh;
        this.modelInstance = _modelInstance;
        _modelInstance.renderRefCount++;
        if (_modelInstance.getTextureInitializer() != null) {
            _modelInstance.getTextureInitializer().renderMain();
        }

        return this;
    }

    public void renderDebug() {
        if (this.m_debugRenderData != null) {
            this.m_debugRenderData.render();
        }
    }

    public void RenderCharacter(ModelSlotRenderData slotData) {
        this.tintR = this.modelInstance.tintR;
        this.tintG = this.modelInstance.tintG;
        this.tintB = this.modelInstance.tintB;
        this.tex = this.modelInstance.tex;
        if (this.tex != null || this.modelInstance.model.tex != null) {
            this.model.DrawChar(slotData, this);
        }
    }

    public void RenderVehicle(ModelSlotRenderData slotData) {
        this.tintR = this.modelInstance.tintR;
        this.tintG = this.modelInstance.tintG;
        this.tintB = this.modelInstance.tintB;
        this.tex = this.modelInstance.tex;
        if (this.tex != null || this.modelInstance.model.tex != null) {
            this.model.DrawVehicle(slotData, this);
        }
    }

    public static Matrix4f makeAttachmentTransform(ModelAttachment modelAttachment, Matrix4f matrix4f) {
        matrix4f.translation(modelAttachment.getOffset());
        org.joml.Vector3f vector3f = modelAttachment.getRotate();
        matrix4f.rotateXYZ(vector3f.x * (float) (Math.PI / 180.0), vector3f.y * (float) (Math.PI / 180.0), vector3f.z * (float) (Math.PI / 180.0));
        return matrix4f;
    }

    public static void applyBoneTransform(ModelInstance modelInstancex, String string, Matrix4f matrix4f2) {
        if (modelInstancex != null && modelInstancex.AnimPlayer != null) {
            if (!StringUtils.isNullOrWhitespace(string)) {
                int _int = modelInstancex.AnimPlayer.getSkinningBoneIndex(string, -1);
                if (_int != -1) {
                    org.lwjgl.util.vector.Matrix4f matrix4f0 = modelInstancex.AnimPlayer.GetPropBoneMatrix(_int);
                    Matrix4f matrix4f1 = ((BaseVehicle.Matrix4fObjectPool)BaseVehicle.TL_matrix4f_pool.get()).alloc();
                    PZMath.convertMatrix(matrix4f0, matrix4f1);
                    matrix4f1.transpose();
                    matrix4f2.mul(matrix4f1);
                    ((BaseVehicle.Matrix4fObjectPool)BaseVehicle.TL_matrix4f_pool.get()).release(matrix4f1);
                }
            }
        }
    }

    public ModelInstanceRenderData transformToParent(ModelInstanceRenderData parentData) {
        if (this.modelInstance instanceof VehicleModelInstance || this.modelInstance instanceof VehicleSubModelInstance) {
            return this;
        } else if (parentData == null) {
            return this;
        } else {
            this.xfrm.set(parentData.xfrm);
            this.xfrm.transpose();
            Matrix4f matrix4f = ((BaseVehicle.Matrix4fObjectPool)BaseVehicle.TL_matrix4f_pool.get()).alloc();
            ModelAttachment modelAttachment0 = parentData.modelInstance.getAttachmentById(this.modelInstance.attachmentNameParent);
            if (modelAttachment0 == null) {
                if (this.modelInstance.parentBoneName != null && parentData.modelInstance.AnimPlayer != null) {
                    applyBoneTransform(parentData.modelInstance, this.modelInstance.parentBoneName, this.xfrm);
                }
            } else {
                applyBoneTransform(parentData.modelInstance, modelAttachment0.getBone(), this.xfrm);
                makeAttachmentTransform(modelAttachment0, matrix4f);
                this.xfrm.mul(matrix4f);
            }

            ModelAttachment modelAttachment1 = this.modelInstance.getAttachmentById(this.modelInstance.attachmentNameSelf);
            if (modelAttachment1 != null) {
                makeAttachmentTransform(modelAttachment1, matrix4f);
                matrix4f.invert();
                this.xfrm.mul(matrix4f);
            }

            if (this.modelInstance.model.Mesh != null && this.modelInstance.model.Mesh.isReady() && this.modelInstance.model.Mesh.m_transform != null) {
                this.xfrm.mul(this.modelInstance.model.Mesh.m_transform);
            }

            if (this.modelInstance.scale != 1.0F) {
                this.xfrm.scale(this.modelInstance.scale);
            }

            this.xfrm.transpose();
            ((BaseVehicle.Matrix4fObjectPool)BaseVehicle.TL_matrix4f_pool.get()).release(matrix4f);
            return this;
        }
    }

    private void testOnBackItem(ModelInstance modelInstancex) {
        if (modelInstancex.parent != null && modelInstancex.parent.m_modelScript != null) {
            AnimationPlayer animationPlayer = modelInstancex.parent.AnimPlayer;
            ModelAttachment modelAttachment0 = null;

            for (int _int = 0; _int < modelInstancex.parent.m_modelScript.getAttachmentCount(); _int++) {
                ModelAttachment modelAttachment1 = modelInstancex.parent.getAttachment(_int);
                if (modelAttachment1.getBone() != null && this.parentBone == animationPlayer.getSkinningBoneIndex(modelAttachment1.getBone(), 0)) {
                    modelAttachment0 = modelAttachment1;
                    break;
                }
            }

            if (modelAttachment0 != null) {
                Matrix4f matrix4f = ((BaseVehicle.Matrix4fObjectPool)BaseVehicle.TL_matrix4f_pool.get()).alloc();
                makeAttachmentTransform(modelAttachment0, matrix4f);
                this.xfrm.transpose();
                this.xfrm.mul(matrix4f);
                this.xfrm.transpose();
                ModelAttachment modelAttachment2 = modelInstancex.getAttachmentById(modelAttachment0.getId());
                if (modelAttachment2 != null) {
                    makeAttachmentTransform(modelAttachment2, matrix4f);
                    matrix4f.invert();
                    this.xfrm.transpose();
                    this.xfrm.mul(matrix4f);
                    this.xfrm.transpose();
                }

                ((BaseVehicle.Matrix4fObjectPool)BaseVehicle.TL_matrix4f_pool.get()).release(matrix4f);
            }
        }
    }

    public static ModelInstanceRenderData alloc() {
        return pool.alloc();
    }

    public static void release(ArrayList<ModelInstanceRenderData> objs) {
        for (int _int = 0; _int < objs.size(); _int++) {
            ModelInstanceRenderData modelInstanceRenderData = (ModelInstanceRenderData)objs.get(_int);
            if (modelInstanceRenderData.modelInstance.getTextureInitializer() != null) {
                modelInstanceRenderData.modelInstance.getTextureInitializer().postRender();
            }

            ModelManager.instance.derefModelInstance(modelInstanceRenderData.modelInstance);
            modelInstanceRenderData.modelInstance = null;
            modelInstanceRenderData.model = null;
            modelInstanceRenderData.tex = null;
            modelInstanceRenderData.softwareMesh = null;
            modelInstanceRenderData.m_debugRenderData = Pool.tryRelease(modelInstanceRenderData.m_debugRenderData);
        }

        pool.release(objs);
    }
}
